/* Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.yzbdl.lanius.orchestrate.common.utils.cron;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import org.quartz.CronExpression;
import org.quartz.TriggerUtils;
import org.quartz.impl.triggers.CronTriggerImpl;

/**
 * Cron表达式工具类
 *
 * @author jinchunzhao@yzbdl.ac.cn
 * @date 2022-04-11 16:11
 */
public class CronUtils {

    /**
     * 返回一个布尔值代表一个给定的Cron表达式的有效性
     *
     * @param cronExpression
     *        Cron表达式
     * @return
     *        true/false
     */
    public static Boolean isValid(String cronExpression) {
        return CronExpression.isValidExpression(cronExpression);
    }

    /**
     * 返回一个字符串值，表示该Cron表达式无效
     *
     * @param cronExpression
     *        Cron表达式
     * @return String
     *        无效：返回表达式错误描述，有效：返回null;
     */
    public static String getInvalidMessage(String cronExpression) {
        try {
            new CronExpression(cronExpression);
            return null;
        } catch (ParseException e) {
            return e.getMessage();
        }
    }

    /**
     * 根据指定的Cron表达式返回下一个执行时间
     *
     * @param cronExpression
     *        Cron表达式
     * @return Date
     *         下次执行的Cron表达式
     *
     */
    public static String getNextExecution(String cronExpression) {
        try {
            CronExpression cron = new CronExpression(cronExpression);
            Date nextDate = cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
            String nextDateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(nextDate);
            return nextDateStr;
        } catch (ParseException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }


    /**
     * 判断当前cron表达式是否是合法的或者过去的时间
     *
     * @param cronExpression
     *        cron表达式
     * @return
     *       true：合法 false：不合法
     */
    public static Boolean validLegalDate(String cronExpression){
        try {
            CronExpression cron = new CronExpression(cronExpression);
            Date nextDate = cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
            if (Objects.isNull(nextDate) || nextDate.before(new Date())){
                return false;
            }
            return true;

        }catch (Exception e){
            return false;
        }
    }

    /**
     * 根据Quartz-Cron表达式获取最近几次执行时间
     *
     * @param cron
     *        cron表达式
     * @return
     *        执行时间
     */
    public static List<String> getRecentTriggerTime(String cron){
        List<String> list = new ArrayList<>();
        try {
            CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
            cronTriggerImpl.setCronExpression(cron);
            List<Date> dates = TriggerUtils.computeFireTimes(cronTriggerImpl, null, 5);
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (Date date : dates) {
                list.add(format.format(date));
            }
        } finally {
            return list;
        }
    }


    public static void main(String[] args) {
        String saa = "3/5 * * * * ? *";
        Boolean valid = isValid(saa);
        System.out.println(valid);
    }
}
